package com.maimang.platform.common.utils.encryption;

import com.sun.crypto.provider.SunJCE;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;

/**
 * @author Rocky
 * @version 1.0
 * @description DES加密算法
 * @class_name DESEncrypt
 * @date 2018-06-14
 * @time 14:27
 */
public class DESEncrypt {

	private static String defaultKey = "zhaojintao";
	private Cipher encryptCiper = null;
	private Cipher decryptCiper = null;

	public DESEncrypt() throws Exception {
		this(defaultKey);
	}

	/**
	 * 指定密钥构造方法
	 *
	 * @param strKey 指定的密钥
	 * @throws Exception
	 */
	public DESEncrypt(String strKey) throws Exception {
		Security.addProvider(new SunJCE());
		Key key = getKey(strKey.getBytes());
		encryptCiper = Cipher.getInstance("DES");
		encryptCiper.init(Cipher.ENCRYPT_MODE, key);
		decryptCiper = Cipher.getInstance("DES");
		decryptCiper.init(Cipher.DECRYPT_MODE, key);
	}

	/**
	 * 加密字符串
	 *
	 * @param plaintext 需要加密的明文字符串
	 * @return 加密后的密文字符串
	 * @throws Exception
	 */
	public String encrypt(String plaintext) throws Exception {
		return byteArrToHexStr(encrypt(plaintext.getBytes()));
	}

	/**
	 * 加密字节数组
	 *
	 * @param bytes 需要加密的目标字节数组
	 * @return 加密后的字节数组
	 * @throws Exception
	 */
	public byte[] encrypt(byte[] bytes) throws Exception {
		return encryptCiper.doFinal(bytes);
	}

	/**
	 * 解密字符串
	 *
	 * @param ciphertext 需要解密的密文字符串
	 * @return 解密后的字符串
	 * @throws Exception
	 */
	public String decrypt(String ciphertext) throws Exception {
		return new String(decrypt(hexStrToByteArr(ciphertext)));
	}

	/**
	 * 解密字节数组
	 *
	 * @param byteArr 需要解密的字节数组
	 * @return 解密后的字节数组
	 * @throws Exception
	 */
	public byte[] decrypt(byte[] byteArr) throws Exception {
		return decryptCiper.doFinal(byteArr);
	}

	/**
	 * 将byte数组转换为16进制的字符串
	 * 如：byte[]{8,18}转换为0813
	 * 与hexStrToByteArr互为可逆过程
	 *
	 * @param byteArr
	 * @return
	 */
	public String byteArrToHexStr(byte[] byteArr) throws Exception {
		int len = byteArr.length;
		StringBuffer stringBuffer = new StringBuffer(len * 2);
		for (int i = 0; i < len; i++) {
			int intTemp = byteArr[i];
			while (intTemp < 0) {
				intTemp += 256;
			}
			if (intTemp < 16) {
				stringBuffer.append("0");
			}
			stringBuffer.append(Integer.toString(intTemp, 16));
		}
		return stringBuffer.toString();
	}

	/**
	 * 将表示16进制的字符串转换为byte数组
	 * 与byteArrToHexStr互为可逆转换过程
	 *
	 * @param text 需要转换的源字符串
	 * @return 转换后的byte数组
	 * @throws Exception
	 */
	public byte[] hexStrToByteArr(String text) throws Exception {
		byte[] byteArr = text.getBytes();
		int len = byteArr.length;
		byte[] byteOut = new byte[len / 2];
		for (int i = 0; i < len; i = i + 2) {
			String strTemp = new String(byteArr, i, 2);
			byteOut[i / 2] = (byte) Integer.parseInt(strTemp, 16);
		}
		return byteOut;
	}

	/**
	 * 从指定字符串生成密钥，密钥所需的字节数组长度为8位
	 * 不足8位时后面补0，超出8位时只取前8位
	 *
	 * @param arrByteTemp 构成该字符串的字节数组
	 * @return 生成的密钥
	 * @throws Exception
	 */
	private Key getKey(byte[] arrByteTemp) throws Exception {
		byte[] arrByte = new byte[8];
		for (int i = 0; i < arrByteTemp.length && i < arrByte.length; i++) {
			arrByte[i] = arrByteTemp[i];
		}
		Key key = new SecretKeySpec(arrByte, "DES");
		return key;
	}
}
